package cn.sciento.core.net;

import cn.sciento.core.convertor.ApplicationContextHelper;
import cn.sciento.core.oauth.CustomUserDetails;
import cn.sciento.core.oauth.DetailsHelper;
import cn.sciento.core.properties.CoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.MacSigner;
import org.springframework.security.jwt.crypto.sign.Signer;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Nonnull;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.Key;
import java.util.Enumeration;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

public class RequestHeaderCopyInterceptor implements ClientHttpRequestInterceptor {
    private static final String CACHE_CONTROL_NO_CACHE = "no-cache";

    private Logger logger = LoggerFactory.getLogger(RequestHeaderCopyInterceptor.class);
    private final Set<String> ignoreHeader = new CopyOnWriteArraySet();

    private static final String OAUTH_TOKEN_PREFIX = "Bearer ";

    public RequestHeaderCopyInterceptor() {
    }

    @Nonnull
    public ClientHttpResponse intercept(@Nonnull HttpRequest request, @Nonnull byte[] body, @Nonnull ClientHttpRequestExecution execution) throws IOException {
        try {
            ServletRequestAttributes originRequestAttribute = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
            if (originRequestAttribute != null) {
                HttpServletRequest originHttpServletRequest = originRequestAttribute.getRequest();
                Enumeration<String> originHeaderNames = originHttpServletRequest.getHeaderNames();
                HttpHeaders aimHttpHeaders = request.getHeaders();
                if (originHeaderNames != null) {
                    while(originHeaderNames.hasMoreElements()) {
                        String key = (String)originHeaderNames.nextElement();
                        if (!this.ignoreHeader.contains(key)) {
                            String value = originHttpServletRequest.getHeader(key);
                            aimHttpHeaders.add(key, value);
                        }
                    }
                }

                if (!aimHttpHeaders.containsKey("jwt_token")) {
                    ApplicationContext applicationContext = ApplicationContextHelper.getContext();
                    CoreProperties coreProperties = applicationContext.getBean(CoreProperties.class);
                    ObjectMapper objectMapper = applicationContext.getBean(ObjectMapper.class);
                    Signer signer = new MacSigner(coreProperties.getOauthJwtKey());
                    String token = null;
                    if (SecurityContextHolder.getContext() != null && SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().getDetails() instanceof OAuth2AuthenticationDetails) {
                        OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)SecurityContextHolder.getContext().getAuthentication().getDetails();
                        if (details.getTokenType() != null && details.getTokenValue() != null) {
                            token = details.getTokenType() + " " + details.getTokenValue();
                        } else if (details.getDecodedDetails() instanceof CustomUserDetails) {
                            token = "Bearer " + JwtHelper.encode(objectMapper.writeValueAsString(details.getDecodedDetails()), signer).getEncoded();
                        }
                    }

                    if (token == null) {
                        token = "Bearer " + JwtHelper.encode(objectMapper.writeValueAsString(DetailsHelper.getAnonymousDetails()), signer).getEncoded();
                    }

                    aimHttpHeaders.add("jwt_token", token);
                }

                aimHttpHeaders.add("Cache-Control", "no-cache");
            }
        } catch (Exception var14) {
            logger.warn("can not copy header info automatic", var14.getCause());
        }

        return execution.execute(request, body);
    }
    public void addIgnoreHeader(String key) {
        this.ignoreHeader.add(key);
    }
}
